package com.demo.sharding.algorithm;

import cn.hutool.setting.dialect.Props;
import com.demo.sharding.constant.CommonConstants;
import com.demo.sharding.util.ShardingUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;

/**
 * @Author: WuPeng
 * @Date: 2021/6/11 11:40 上午
 */
public class MyPreciseDBShardingAlgorithm implements PreciseShardingAlgorithm<String> {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 分库虚拟节点数量
     */
    public static int virtualNodeCount;

    /**
     * 分库虚拟节点范围
     */
    public static String virtualNodeCountRang;

    @Override
    public String doSharding(Collection<String> dbNames, PreciseShardingValue<String> preciseShardingValue) {
        Props props = new Props("application-sharding.properties");
        // 初始化分库的虚拟节点数量和范围
        virtualNodeCount = props.getInt(CommonConstants.SHARDING_DATASOURCE_VIRTUAL_NODE_COUNT);
        virtualNodeCountRang = props.getStr(CommonConstants.SHARDING_DATASOURCE_VIRTUAL_NODE_COUNT_RANG);

        int mod = preciseShardingValue.getValue().hashCode() % virtualNodeCount;

        mod = ShardingUtils.getAbsoluteValue(mod);
        // 虚拟节点范围映射到实际物理节点
        Integer shardingValue = ShardingUtils.getPhysicNodeByVisualNode(mod, virtualNodeCountRang);
        for (String each : dbNames) {
            // 将余数与配置的实际数据库名进行匹配
            if (each.endsWith(String.valueOf(shardingValue))) {
                logger.info("logic DB : {}", each);
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}
